package com.jijs.http;

import com.jijs.utils.FileSystemUtil;
import com.jijs.utils.RuntimeEXE;
import com.jijs.utils.Tools;

import java.io.*;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.UUID;

public class CoreServlet {
	private static final int numOfEncAndDec = 0xAA; // 加密解密秘钥

	public static void main(String[] args) {

		String encryptUrl = "/encrypt?sourcefile=adsd1&targetfile=sdsd2";
		String decryptUrl = "/decrypt?filepath=test";
		String readFile = "/readfile?filepath=path";
		String writeFile = "/writefile?filepath=path&content=content";
		String lisense = "/lisense";

		process(encryptUrl);
		process(decryptUrl);
		process(readFile);
		process(writeFile);
		process(lisense);

	}

	public static ProcessorResultBean process(String url) {
		ProcessorResultBean result = new ProcessorResultBean();
		result.setContentType("text/html");

		final String PARAM_SOURCEFILE = "sourcefile";
		final String PARAM_TARGETFILE = "targetfile";
		final String PARAM_FILEPATH = "filepath";
		final String PARAM_CONTENT = "content";

		final String METHOD_ENCRYPT = "/encrypt?";
		final String METHOD_DECRYPT = "/decrypt?";
		final String METHOD_READFILE = "/readfile?";
		final String METHOD_WRITEFILE = "/writefile?";
		final String METHOD_LISENSE = "/license";

		Map<String, String> paramMap = getParameter(url);
		String errorMsg = "";

		/**
		 * 加密文件
		 */
		if (url.startsWith(METHOD_ENCRYPT)) {

			String sourcefile = paramMap.get(PARAM_SOURCEFILE);
			String targetfile = paramMap.get(PARAM_TARGETFILE);

			System.out.println("sourcefile:" + sourcefile);
			System.out.println("targetfile:" + targetfile);
			if (Tools.isNotBlank(sourcefile) && Tools.isNotBlank(targetfile)) {
				File file = new File(sourcefile);
				if (file.exists()) {
					try {
						encrypt(sourcefile, targetfile);
						result.setCode("200");
						String body = new StringBuilder("<HTML>\r\n").append("<HEAD><TITLE>Not Implemented</TITLE>\r\n")
								.append("</HEAD>\r\n").append("<BODY>").append("<H1>Encrypt File Success!</H1>\r\n")
								.append("</BODY></HTML>\r\n").toString();
						result.setContentData(body.getBytes("utf-8"));
						return result;
					} catch (IOException e) {
						errorMsg = "文件加密失败！" + e.getMessage();
					}
				} else {
					errorMsg = "【sourcefile=" + sourcefile + "】文件不存在";
				}
			} else {
				errorMsg = "sourcefile 参数和 targetfile 参数都不能为空！";
			}

			result.setCode("404");
			result.setErrorMsg(errorMsg);
			return result;
		}
		/**
		 * 解密文件
		 */
		else if (url.startsWith(METHOD_DECRYPT)) {
			String filepath = paramMap.get(PARAM_FILEPATH);

			if (Tools.isNotBlank(filepath)) {
				File file = new File(filepath);
				if (file.exists()) {
					try {
						byte data[] = decrypt(file);
						result.setCode("200");
						result.setContentData(data);
						result.setContentType("application/octet-stream");
						result.setDownloadFileName(file.getName());
						return result;
					} catch (IOException e) {
						errorMsg = "文件读取失败！" + e.getMessage();
					}
				} else {
					errorMsg = "【filepath=" + filepath + "】文件不存在";
				}
			} else {
				errorMsg = "filepath 参数都不能为空！";
			}

			result.setCode("404");
			result.setErrorMsg(errorMsg);
			return result;
		}
		/**
		 * 读文件接口
		 */
		else if (url.startsWith(METHOD_READFILE)) {
			String filepath = paramMap.get(PARAM_FILEPATH);

			if (Tools.isNotBlank(filepath)) {
				File file = new File(FileSystemUtil.diskpath, filepath);
				if (file.exists()) {
					try {
						byte[] data = decrypt(file);
						System.out.println(new String(data));
						result.setContentData(data);
						result.setCode("200");
						return result;
					} catch (IOException e) {
						errorMsg = "读取文件失败！";
					}
				} else {
					errorMsg = "【filepath=" + filepath + "】文件不存在";
				}
			} else {
				errorMsg = "filepath 参数都不能为空！";
			}

			result.setCode("404");
			result.setErrorMsg(errorMsg);
			return result;
		}
		/**
		 * 写文件接口
		 */
		else if (url.startsWith(METHOD_WRITEFILE)) {
			String filepath = paramMap.get(PARAM_FILEPATH);
			String content = paramMap.get(PARAM_CONTENT);

			if (Tools.isNotBlank(filepath) && Tools.isNotBlank(content) && filepath.indexOf(":")==-1) {
				File file = new File(FileSystemUtil.diskpath, filepath);
				try {
					writeFile(file, content);
					String body = new StringBuilder("<HTML>\r\n").append("<HEAD><TITLE>Not Implemented</TITLE>\r\n")
							.append("</HEAD>\r\n").append("<BODY>").append("<H1>Write File Success!</H1>")
							.append("</BODY></HTML>\r\n").toString();

					result.setContentData(body.getBytes("utf-8"));
					result.setCode("200");
					return result;
				} catch (UnsupportedEncodingException e) {
					errorMsg = "写入文件失败！";
				}
			} else {
				errorMsg = "filepath 参数都不能为空或不能传入绝对路径！";
			}

			result.setCode("404");
			result.setErrorMsg(errorMsg);
			return result;

		} else if (url.equalsIgnoreCase(METHOD_LISENSE)) {
			if(FileSystemUtil.diskpath!=null && RuntimeEXE.isReadOnly()){
				result.setContentData("6125066220b64010ab0d0957de8f1fa0d0b9b349423e47c5a18e91b5beb6547d".getBytes());
				result.setCode("200");
			}else{
				result.setCode("404");
			}

			return result;
		}

		result.setCode("404");
		result.setErrorMsg("服务器不支持此方法");
		return result;
	}


	private static void writeFile(File file, String content) {
		try {
			System.out.println("-------");
			//防止反编译的处理
			if (654789 == new Random().nextInt()) {
				throw new Exception("fewt43");
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		} finally {
			try {
				//防止反编译的处理
				if (654789 == new Random().nextInt()) {
					throw new Exception("fewt43");
				}
			} catch (Exception ex) {
				System.out.print(ex);
			}
		}

		File parent = file.getParentFile();
		if (parent != null) {
			if (!parent.exists()) {
				parent.mkdirs();
			}
		}

		new Runnable() {
			@Override
			public void run() {
				try (FileOutputStream fos = new FileOutputStream(file)) {

					// if file doesnt exists, then create it
					if (!file.exists()) {
						file.createNewFile();
					}
					// get the content in bytes
					byte[] contentBytes = content.getBytes();
					for (int i = 0; i < contentBytes.length; i++) {
						contentBytes[i] = (byte) (contentBytes[i] ^ numOfEncAndDec);
					}

					fos.write(contentBytes);

				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}.run();
	}


	/**
	 * 解密文件
	 *
	 * @param file
	 * @return 返回解密后的文件流
	 * @throws IOException
	 */
	private static byte[] decrypt(File file) throws IOException {

		try (InputStream input = new FileInputStream(file)) {
			byte[] buf = new byte[(int) file.length()];
			int bytesRead = input.read(buf);
			for (int i = 0; i < bytesRead; i++) {
				buf[i] = (byte) (buf[i] ^ numOfEncAndDec);
			}
			return buf;
		}
	}

	/**
	 * 加密文件
	 *
	 * @param sourcefile
	 * @param targetfile
	 * @throws IOException
	 */
	private static void encrypt(String sourcefile, String targetfile) throws IOException {
		File source = new File(sourcefile);
		File target = new File(targetfile);

		File parent = target.getParentFile();
		if (!parent.exists()) {
			parent.mkdirs();
		}

		try (InputStream input = new FileInputStream(source); OutputStream output = new FileOutputStream(target);) {
			byte[] buf = new byte[1024];
			int bytesRead;
			while ((bytesRead = input.read(buf)) > 0) {
				for (int i = 0; i < bytesRead; i++) {
					buf[i] = (byte) (buf[i] ^ numOfEncAndDec);
				}
				output.write(buf, 0, bytesRead);
			}
		}
	}

	/**
	 * 获取请求参数
	 *
	 * @param url
	 * @return
	 */
	public static Map<String, String> getParameter(String url) {
		Map<String, String> map = new HashMap<String, String>();

		if (url.indexOf("?") == -1) {
			return map;
		}

		String paramStr = url.substring(url.indexOf("?") + 1);
		String params[] = paramStr.split("&");

		for (String param : params) {
			String[] arr = param.split("=");
			try {
				map.put(arr[0], URLDecoder.decode(arr[1],"utf-8"));
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
		}
		return map;
	}
}
